package org.c3sl.ufpr.br.exercises.tables;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextPane;
import javax.swing.JViewport;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import net.java.balloontip.BalloonTip;
import net.java.balloontip.TablecellBalloonTip;
import net.java.balloontip.styles.EdgedBalloonStyle;
import org.c3sl.ufpr.br.correction.Correction;
import org.c3sl.ufpr.br.fractal.Drawing;
import org.c3sl.ufpr.br.fractal.Fractal;
import br.ufpr.c3sl.state.SaveState;
import br.ufpr.c3sl.view.footer.paginator.PaginatorEvent;
import br.ufpr.c3sl.view.footer.paginator.PaginatorListener;
import br.ufpr.c3sl.view.principal.JpCarrie;
import br.ufpr.c3sl.virtualkeyboard.events.VirtualKeyBoardEvent;
import br.ufpr.c3sl.virtualkeyboard.formula.ElementOfFormula;
import br.ufpr.c3sl.virtualkeyboard.formula.FormulaInitial;
import br.ufpr.c3sl.virtualkeyboard.listeners.VirtualKeyBoardListener;
import br.ufpr.c3sl.virtualkeyboard.main.VirtualKeyBoardMain;
@SuppressWarnings("serial")
public abstract class JExerciseTable extends JTable implements VirtualKeyBoardListener, SaveState, PaginatorListener{
private TableModel model = new TableModel();
private String axiom;
private String rules;
private double angle;
transient protected VirtualKeyBoardMain keyBoard;
transient protected TablecellBalloonTip balloonMessage;
protected boolean[][] cellEditable;
private boolean[][] isRowCollumnCorrect;
private Correction correction;
private int numberRow;
private int numberColumn;
public JExerciseTable(String axiom, String rules, double angle, Correction correction,
int numberRow, int numberColumn) {
this.axiom = axiom;
this.rules = rules;
this.angle = angle;
this.setModel(model);
this.correction = correction;
this.numberColumn = numberColumn;
this.numberRow = numberRow;
this.isRowCollumnCorrect = new boolean[numberRow+1][numberColumn+1];
configureModel();
configureFractal();
buildEventsAndTransientvariables();
configureEditable();
JpCarrie.getInstance().getPaginator().addPaginatorListener(this);
}
public boolean isRowCollumnCorrect(int row, int column){
return isRowCollumnCorrect[row][column];
}
public void setRowCollumnCorrect(int row, int column, boolean correct){
this.isRowCollumnCorrect[row][column] = correct;
}
public void configureEditable(){
cellEditable = new boolean[numberRow+1][numberColumn];
cellEditable[0][2] = true;
}
private void configureModel(){
Enumeration<TableColumn> columns = this.getColumnModel().getColumns();
MultiLineHeaderRenderer renderer = new MultiLineHeaderRenderer();
while (columns.hasMoreElements()) {
TableColumn column = columns.nextElement();
column.setMinWidth(16);
column.setHeaderRenderer(renderer);
column.setCellRenderer(new Renderer(getDefaultRenderer(JPanel.class)));
}
this.getColumnModel().getColumn(0).setMaxWidth(100);
this.getColumnModel().getColumn(0).setPreferredWidth(100);
this.getColumnModel().getColumn(1).setMaxWidth(148);
this.getColumnModel().getColumn(1).setPreferredWidth(148);
this.setRowHeight(128);
this.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
this.setBackground(new Color(220,226,225));
this.setSelectionBackground(new Color(220,226,225));
this.getTableHeader().setReorderingAllowed(false);
this.getTableHeader().setBackground(Color.white);
}
public boolean getFractalPaintColor(){
return false;
}
private void configureFractal(){
for (int i = 0; i < numberRow; i++) {
Fractal fractal = new Fractal(this.axiom, this.rules, this.angle, i);
Drawing drawing = new Drawing(true);
drawing.setPaintWithColor(getFractalPaintColor());
drawing.setFractal(fractal);
JPanel jpFractal = new JPanel(new BorderLayout());
jpFractal.add(drawing, BorderLayout.CENTER);
model.addRow(new Object[] { i, jpFractal });
model.setValueAt(new FormulaInitial(), i, 2);
}
model.addRow(new Object[] { "n", "figura limite"});
model.setValueAt(new FormulaInitial(), numberRow, 2);
}
public abstract String[] arrayHeader();
private class TableModel extends DefaultTableModel{
public TableModel() {
super(new Object[][]{}, arrayHeader());
}
@Override
public boolean isCellEditable(int row, int column) {
if(cellEditable[row][column]){
showKeyBoard(row, column);
}else
keyBoard.setVisible(false);
return false;
}
}
@Override
public void formulaSended(VirtualKeyBoardEvent<JPanel> formula) {
if (correction.isCorrect(formula.getSource().toString(), getSelectedRow(), getSelectedColumn())){
processCorrectAnswer(formula.getSource());
}else{
processWrongAnswer(formula.getSource());
}
keyBoard.setVisible(false);
}
private void processCorrectAnswer(JPanel answer){
setValueAt(answer, getSelectedRow(), getSelectedColumn());
setRowCollumnCorrect(getSelectedRow(), getSelectedColumn(), true);
activeCell(true);
answer.setLayout(new FlowLayout());
answer.setBorder(BorderFactory.createTitledBorder(
new LineBorder(new Color(0, 150, 0), 5), "Correto",
TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.CENTER, getFont(), Color.black));
}
private void processWrongAnswer(JPanel answer){
setRowCollumnCorrect(getSelectedRow(), getSelectedColumn(), false);
activeCell(false);
answer.setLayout(new FlowLayout());
setValueAt(answer, getSelectedRow(), getSelectedColumn());
answer.setBorder(BorderFactory.createTitledBorder(
new LineBorder(new Color(250, 0, 0), 5), "Incorreto",
TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.CENTER, getFont(), Color.black));
showMessageErrorIfNecessary();
JpCarrie.getInstance().saveState(correction.getMistakeInfo());
}
private void showMessageErrorIfNecessary() {
if (correction.thereIsMessage()) {
JTextPane paneMsg = new JTextPane();
paneMsg.setContentType("text/html");
paneMsg.setBackground(Color.RED);
paneMsg.setText(correction.getErrorMessage());
paneMsg.setEditable(false);
balloonMessage = new TablecellBalloonTip(this, paneMsg,
getSelectedRow(), getSelectedColumn()-1,
new EdgedBalloonStyle(Color.RED, Color.WHITE),
BalloonTip.Orientation.RIGHT_ABOVE,
BalloonTip.AttachLocation.NORTHEAST,
60, 20,
true);
balloonMessage.setViewport((JViewport) this.getParent());
}
}
private void closeBallonTip(){
if (balloonMessage != null){
balloonMessage.closeBalloon();
balloonMessage = null;
}
}
public void activeCell(boolean _true){
if (getSelectedRow() != 0){
cellEditable[getSelectedRow()-1][getSelectedColumn()] = !_true;
}
if (getSelectedRow() < getRowCount()-1)
cellEditable[getSelectedRow()+1][getSelectedColumn()] = _true;
}
private void showKeyBoard(int row, int column){
closeBallonTip();
if(row == numberRow)
keyBoard.enableVariableN();
this.keyBoard.setFormula((ElementOfFormula) getValueAt(row, column));
this.keyBoard.setVisible(true);
}
@Override
public void paginated(PaginatorEvent<Object> event) {
this.keyBoard.setVisible(false);
closeBallonTip();
}
public int getMaxHeaderLength(){
return 20;
}
class Renderer implements TableCellRenderer, Serializable {
private DefaultTableCellRenderer __defaultRenderer;
public Renderer(TableCellRenderer renderer) {
__defaultRenderer = (DefaultTableCellRenderer) renderer;
__defaultRenderer.setHorizontalAlignment(SwingConstants.CENTER);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if(value instanceof Component) {
((Component)value).setBackground(null);
return (Component)value;
}
return __defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
class MultiLineHeaderRenderer extends JList implements TableCellRenderer, Serializable {
private static final long serialVersionUID = 1L;
public MultiLineHeaderRenderer() {
setOpaque(true);
setForeground(UIManager.getColor("TableHeader.foreground"));
setBackground(UIManager.getColor("TableHeader.background"));
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
ListCellRenderer renderer = getCellRenderer();
((JLabel) renderer).setHorizontalAlignment(SwingConstants.CENTER);
setCellRenderer(renderer);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setFont(table.getFont());
String str = (value == null) ? "" : value.toString(), line = "";
String[] words = str.split(" ");
int maxLen = getMaxHeaderLength();
Vector<String> v = new Vector<String>();
try {
for (int i = 0; i < words.length; i++) {
int len = line.length() + words[i].length();
if (len < maxLen) {
line += words[i] + " ";
}
else {
v.addElement(line);
line = words[i] + " ";
}
}
}
catch (Exception e) {
System.out.println(e.getMessage());
}
v.addElement(line);
setListData(v);
return this;
}
}
}